package com.community.auth.controller;

import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSONObject;
import com.community.auth.feign.ManageRemote;
import com.community.common.entity.resp.JwtResponse;
import com.community.common.entity.vo.SendSmsParamVo;
import com.community.common.entity.vo.UserLoginVo;
import com.community.common.result.Result;
import com.community.common.utils.JwtUtils;
import com.community.common.utils.StringUtils;
import lombok.extern.log4j.Log4j2;
import org.springframework.amqp.rabbit.core.RabbitMessagingTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("/login")
@Log4j2
public class LoginController {

    @Autowired
    HttpServletRequest request;

    @Autowired
    RedisTemplate<String,Object> redisTemplate;

    @Autowired
    RabbitMessagingTemplate rabbitMessagingTemplate;

    @Autowired
    ManageRemote manageRemote;

    /**
     * 发送验证码
     * @param phone
     * @return
     */
    @PostMapping("/sendSms/{phone}")
    public Result<String> sendCode(@PathVariable String phone){
        log.info("请求路径：【{}】，请求方式：【{}】，请求参数：【{}】",
                request.getRequestURI(),request.getMethod(), phone);


        SendSmsParamVo sendSmsParamVo = new SendSmsParamVo();
        sendSmsParamVo.setMsgId(RandomUtil.randomNumbers(10));
        sendSmsParamVo.setPhone(phone);

        rabbitMessagingTemplate.convertAndSend("community.direct","send.sms",JSONObject.toJSONString(sendSmsParamVo));

        Result<String> result=Result.success("发送成功");
        log.info("请求路径：【{}】，请求方式：【{}】，响应结果：【{}】",
                request.getRequestURI(),request.getMethod(), result);

        return result;
    }

    /**
     * 手机号验证码登录
     * @param userLoginVo
     * @return
     */
    @PostMapping("/phoneAndCodeLogin")
    public Result<JwtResponse> phoneAndCodeLogin(@RequestBody UserLoginVo userLoginVo){
        log.info("请求路径：【{}】，请求方式：【{}】，请求参数：【{}】",
                request.getRequestURI(),request.getMethod(), JSONObject.toJSONString(userLoginVo));
        Result<JwtResponse> result=null;

        // 手机号 验证码不能为空
        if(StringUtils.isEmpty(userLoginVo.getPhone()) || StringUtils.isEmpty(userLoginVo.getCode())){
            result = Result.error("手机号 验证码 不能为空");
            log.info("请求路径：【{}】，请求方式：【{}】，响应结果：【{}】",
                    request.getRequestURI(),request.getMethod(), result);
            return result;
        }
        // 查找用户
        Result<UserLoginVo> userByPhone = manageRemote.findUserByPhone(userLoginVo.getPhone());

        // 降级
        if(userByPhone.getCode() == Result.FAIL) {
            result = Result.error(userByPhone.getMsg());
            log.info("请求路径：【{}】，请求方式：【{}】，响应结果：【{}】",
                    request.getRequestURI(),request.getMethod(), result);

            return result;
        }

        // 获取数据
        UserLoginVo data = userByPhone.getData();

        // 手机号不存在
        if(data == null ){
            result = Result.error("手机号不存在");
            log.info("请求路径：【{}】，请求方式：【{}】，响应结果：【{}】",
                    request.getRequestURI(),request.getMethod(), result);
            return result;
        }
        // 验证码错误
        String code = String.valueOf(redisTemplate.opsForValue().get("tel_code:" + userLoginVo.getPhone()));
        if(!code.equals(userLoginVo.getCode())) {
            result = Result.error("验证码错误");
            log.info("请求路径：【{}】，请求方式：【{}】，响应结果：【{}】",
                    request.getRequestURI(),request.getMethod(), result);
            return result;
        }

        // 生成 token
        String userKey = UUID.randomUUID().toString().replaceAll("-", "");
        Map<String, Object> jwtMap = new HashMap<>();
        jwtMap.put(JwtUtils.USER_KEY, userKey);
        jwtMap.put(JwtUtils.DETAILS_USER_ID, data.getId());
        String token = JwtUtils.createToken(jwtMap);

        // 存入redis
        redisTemplate.opsForValue().set(JwtUtils.LOGIN_TOKEN_KEY + userKey, JSONObject.toJSONString(data), 100, TimeUnit.MINUTES);
        JwtResponse jwtResponse = new JwtResponse();
        jwtResponse.setToken(token);
        jwtResponse.setExpireTime("100MIN");

        result = Result.success(jwtResponse);
        log.info("请求路径：【{}】，请求方式：【{}】，响应结果：【{}】",
                request.getRequestURI(),request.getMethod(), result);

        return result;
    }

    @PostMapping("/loginUrl")
    public Result<JwtResponse> loginUrl(@RequestBody UserLoginVo userLoginVo){
        log.info("请求路径：【{}】，请求方式：【{}】，请求参数：【{}】",
                request.getRequestURI(),request.getMethod(), JSONObject.toJSONString(userLoginVo));
        Result<JwtResponse> result=null;

        // 手机号 验证码不能为空
        if(StringUtils.isEmpty(userLoginVo.getPhone()) || StringUtils.isEmpty(userLoginVo.getCode())){
            result = Result.error("手机号 验证码 不能为空");
            log.info("请求路径：【{}】，请求方式：【{}】，响应结果：【{}】",
                    request.getRequestURI(),request.getMethod(), result);
            return result;
        }
        // 查找用户
        Result<UserLoginVo> userByPhone = manageRemote.findUserByPhone(userLoginVo.getPhone());

        // 降级
        if(userByPhone.getCode() == Result.FAIL) {
            result = Result.error(userByPhone.getMsg());
            log.info("请求路径：【{}】，请求方式：【{}】，响应结果：【{}】",
                    request.getRequestURI(),request.getMethod(), result);

            return result;
        }

        // 获取数据
        UserLoginVo data = userByPhone.getData();

        // 手机号不存在
        if(data == null ){
            result = Result.error("手机号不存在");
            log.info("请求路径：【{}】，请求方式：【{}】，响应结果：【{}】",
                    request.getRequestURI(),request.getMethod(), result);
            return result;
        }
        // 验证码错误
        String code = String.valueOf(redisTemplate.opsForValue().get("tel_code:" + userLoginVo.getPhone()));
        if(!code.equals(userLoginVo.getCode())) {
            result = Result.error("验证码错误");
            log.info("请求路径：【{}】，请求方式：【{}】，响应结果：【{}】",
                    request.getRequestURI(),request.getMethod(), result);
            return result;
        }

        // 生成 token
        String userKey = UUID.randomUUID().toString().replaceAll("-", "");
        Map<String, Object> jwtMap = new HashMap<>();
        jwtMap.put(JwtUtils.USER_KEY, userKey);
        jwtMap.put(JwtUtils.DETAILS_USER_ID, data.getId());
        String token = JwtUtils.createToken(jwtMap);

        // 存入redis
        redisTemplate.opsForValue().set(JwtUtils.LOGIN_TOKEN_KEY + userKey, JSONObject.toJSONString(data), 100, TimeUnit.MINUTES);
        JwtResponse jwtResponse = new JwtResponse();
        jwtResponse.setToken(token);
        jwtResponse.setExpireTime("100MIN");
        result = Result.success(jwtResponse);
        redisTemplate.opsForValue().set("url:"+data.getId(),userLoginVo.getUrl());

        log.info("请求路径：【{}】，请求方式：【{}】，响应结果：【{}】",
                request.getRequestURI(),request.getMethod(), result);

        return result;
    }

    /**
     * 账号密码登录
     * @param userLoginVo
     * @return
     */
    @PostMapping("/login")
    public Result<JwtResponse> login(@RequestBody UserLoginVo userLoginVo){
        log.info("请求路径：【{}】，请求方式：【{}】，请求参数：【{}】",
                request.getRequestURI(),request.getMethod(), JSONObject.toJSONString(userLoginVo));

        Result<JwtResponse> result=Result.success();
        log.info("请求路径：【{}】，请求方式：【{}】，响应结果：【{}】",
                request.getRequestURI(),request.getMethod(), result);

        return result;
    }


    /**
     * 登出
     */
    @PostMapping("/layout")
    public Result layout(){
        //获取token
        String token = request.getHeader(JwtUtils.TOKEN);
        //解析token
        String userKey = JwtUtils.getUserKey(token);
        redisTemplate.delete(JwtUtils.LOGIN_TOKEN_KEY+userKey);
        return Result.success();
    }

    /**
     * 获取数据
     * @return
     */
    @GetMapping("/info")
    public Result<UserLoginVo> info(){
        //获取token
        String token = request.getHeader(JwtUtils.TOKEN);
        //解析token
        String userKey = JwtUtils.getUserKey(token);
        //获取用户数据
        String userJson = String.valueOf(redisTemplate.opsForValue().get(JwtUtils.LOGIN_TOKEN_KEY + userKey));
        //反序列化
        UserLoginVo user = JSONObject.parseObject(userJson, UserLoginVo.class);

        return Result.success(user);
    }

}
